home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_08_03 / 8n03090a < prev    next >
Text File  |  1990-03-18  |  8KB  |  287 lines

  1. /* Speech Recognizer */
  2.  
  3. /* bj gleason, Upsala College, Computer Science Department */
  4. /* East Orange, nj  07019   (201)-998-1037                 */
  5.  
  6. #include <stdio.h>
  7. #include <conio.h>
  8.  
  9. #define RAWBUFFERSIZE 150  /* 100 samples/second 1.5 seconds   */
  10. #define VOCABSIZE 10       /* 10 digits, 0 - 9                 */
  11. #define NUMSAMPLES 16      /* Number of samples to extract     */
  12. #define NUMBANDS 4         /* High, Low Freq, High, Low Energy */
  13. #define BIGNUM 32767       /* large number for min diff. calc  */
  14.  
  15.  
  16. int rawspeech[RAWBUFFERSIZE][NUMBANDS];  /* to hold raw speech */
  17. int index[VOCABSIZE];            /* inidicate if digit trained */
  18. int template[VOCABSIZE][NUMSAMPLES][NUMBANDS]; /* known templates  */
  19. int unknown[NUMSAMPLES][NUMBANDS];       /* unknown voice template */
  20. int min_diff[VOCABSIZE];                 /* min diff. each digit   */
  21. int sam_size;                            /* current sample size */
  22. int debug;                               /* show debugging info */
  23.  
  24. /* getspeech will read in a file from disk.  The length in bytes */
  25. /* will be returned.  The rawspeech buffer will be modified.     */
  26. int getspeech()
  27. {
  28.  FILE *fptr;
  29.  int i,j;
  30.  char fname[80];
  31.  
  32.    if (debug) printf("\nReading in Speech");
  33.    printf("\nEnter name of file?");
  34.    gets(fname);
  35.    if ((fptr=fopen(fname,"rt"))==NULL)
  36.        {
  37.      printf("\nCant find file %s",fname);
  38.      return(0);
  39.        }
  40.    else
  41.        {
  42.      for(i=0;i<=RAWBUFFERSIZE;i++)
  43.        for(j=0;j < NUMBANDS;j++)
  44.           {
  45.         if ((fscanf(fptr,"%i",&rawspeech[i][j]))==EOF)
  46.            {
  47.              fclose(fptr);
  48.              return(i);
  49.            }
  50.           }
  51.        }
  52. }
  53.  
  54. int plot_it()
  55. {
  56.  int i,j,x,y;
  57.  
  58.  printf("\n\n");
  59.  for (i=0;i < sam_size;i++)
  60.    {
  61.      for (j=NUMBANDS-1; j >= 0; j--)
  62.       {
  63.     x=rawspeech[i][j]+(j*2);
  64.     gotoxy(x,wherey());
  65.     putchar(j+48);
  66.       }
  67.    printf("\n");
  68.    }
  69. }
  70.  
  71. /* the closest match routine compares the unknown template with  */
  72. /* known templates.  It builds a minimim difference list that is */
  73. /* the difference between unknown and each known.   We then scan */
  74. /* list to find the closest match.                               */
  75. int closest_match()
  76. {
  77.  int p,i,j;
  78.  int low,next_low,digit,next_digit;
  79.  
  80.    if (debug) printf("\nFinding Closest Match");
  81.  
  82.    for (p = 0; p < VOCABSIZE; p++)
  83.        if (index[p] != 0)
  84.       {
  85.         min_diff[p] = 0;
  86.         for(i = 0; i < NUMSAMPLES; i++)
  87.            for(j = 0; j < NUMBANDS; j++)
  88.           /* for each digit, find the absoulte difference */
  89.           /* between known and unknown templates          */
  90.           min_diff[p] = min_diff[p] + abs(unknown[i][j]
  91.                           -template[p][i][j]);
  92.       }
  93.        else
  94.       {
  95.         min_diff[p]=BIGNUM;  /* put in a big number if digit not */
  96.       }                      /* trained.                         */
  97.  
  98.    /* min_diff now has the difference for each template.  Search */
  99.    /* to find the smallest difference.  This will be our digit.  */
  100.    /* Find the next lowest match to calculate the delta diff.    */
  101.    digit = -1;
  102.    next_digit = -1;
  103.    low = BIGNUM;
  104.    next_low = BIGNUM;
  105.    if (debug) printf("\nTP# Diff  Low  Digit");
  106.    for (p = 0; p < VOCABSIZE; p++)
  107.        {
  108.      if(min_diff[p] < low)
  109.        {
  110.          next_low = low;
  111.          next_digit = digit;
  112.          digit = p;
  113.          low = min_diff[p];
  114.        }
  115.      if (debug) printf("\n%3i %5i %5i %2i",p,min_diff[p],low,digit);
  116.        }
  117.    if (debug == 1)
  118.       {
  119.     printf("\nMinimun Difference was %i, Digit is %i",low,digit);
  120.     printf("\nNext Closest Diff  was %i, Digit is %i",next_low
  121.                              ,next_digit);
  122.     printf("\nWith the delta difference of %i",next_low-low);
  123.       }
  124.  
  125.    /* it would be right here where your would add the code   */
  126.    /* to set a rejection limit or a delta difference limit.  */
  127.    /* If the digit is rejected, send back error, such as -1. */
  128.    return(digit);
  129. }
  130.  
  131. /* Extract template will extract a template from the raw    */
  132. /* speech buffer.  This is to reduce the size of the        */
  133. /* template and to elimate time warping.                    */
  134. /* the rate is kept in floating point to prevent truncation */
  135. /* errors.                                                  */
  136. int extract_template()
  137. {
  138.  int i,j,p;
  139.  float rate,x;
  140.  
  141.   if (debug) printf("\nExtracting Template");
  142.    rate = (float) sam_size / NUMSAMPLES;
  143.    p = 0;
  144.    if (debug)
  145.       {
  146.     printf("\nExtracting %i elements from Raw Speech",
  147.                             NUMSAMPLES);
  148.     printf("\nTake every %f element", rate);
  149.     printf("\n\n UN  RS");
  150.       }
  151.    for (x = 0; x < sam_size ; x = x + rate)
  152.        {
  153.      for (j = 0; j < NUMBANDS; j++)
  154.          unknown[p][j] = rawspeech[(int)x][j];
  155.      if (debug) printf("\n%3i %3i",p,(int)x);
  156.      p++;
  157.        }
  158. }
  159.  
  160. /* During the training phase, this will take the extracted template  */
  161. /* and store it in the array of known templates.                     */
  162. int store_template(int position)
  163. {
  164.   int i,j;
  165.  
  166.   if (debug) printf("\nStoring template at position %i",position);
  167.   for (i = 0; i < NUMSAMPLES ; i++)
  168.       for (j = 0; j < NUMBANDS; j++)
  169.       {
  170.         template[position][i][j] = unknown[i][j];
  171.       }
  172. }
  173.  
  174. /* Perform - Get the speech, extract an unknown template, compare  */
  175. /*   against the rest, and print the resulting digit.              */
  176. int perform()
  177. {
  178.  int digit;
  179.  
  180.     sam_size = getspeech();
  181.     if (debug) plot_it();
  182.     if (debug) printf("\nSize of Sample = %i",sam_size);
  183.  
  184.     extract_template();       /* break raw buffer up and     */
  185.                /* place into unknown template */
  186.  
  187.     digit = closest_match();
  188.     printf("\nDigit spoken was %i",digit);
  189.  
  190. }
  191.  
  192. /* Training -  Get the speech, extract an unknown template, */
  193. /* find from the user what digit it was, then store it in   */
  194. /* the known template array.                                */
  195. int train()
  196. {
  197.  char ans[10];
  198.  int digit;
  199.  
  200.    sam_size = getspeech();
  201.    if (debug) plot_it();
  202.    if (debug) printf("\nSize of Sample = %i",sam_size);
  203.    printf("\nEnter the digit spoken ?");
  204.    gets(ans);
  205.    digit = atoi(ans);
  206.  
  207.    index[digit] = 1;       /* indicate this digit is trained */
  208.  
  209.    extract_template();       /* break raw buffer up and     */
  210.                /* place into unknown template */
  211.  
  212.    store_template(digit);  /* store the template          */
  213.  
  214. }
  215.  
  216. /* Eztrain -  This is to quickly load in files a0 - a9 */
  217. int eztrain(char fname[80], int digit)
  218. {
  219.  FILE *fptr;
  220.  int i,j;
  221.  
  222.    if ((fptr=fopen(fname,"rt"))!=NULL)
  223.        {
  224.     sam_size = 0;
  225.     printf("\nReading file %s", fname);
  226.     for(i=0;i<=RAWBUFFERSIZE;i++)
  227.        for(j=0;j < NUMBANDS;j++)
  228.           if ((fscanf(fptr,"%i",&rawspeech[i][j]))!=EOF)
  229.          sam_size = i;
  230.     fclose(fptr);
  231.     if (debug) plot_it();
  232.     if (debug) printf("\nSize of Sample = %i",sam_size);
  233.     index[digit] = 1;
  234.     extract_template();
  235.     store_template(digit);
  236.        }
  237. }
  238.  
  239.  
  240. main()
  241. {
  242.  int i;
  243.  char ans[80];
  244.  char choice;
  245.  
  246.  /* clear the training index... nothing has been entered */
  247.  for (i=0; i<VOCABSIZE; i++)
  248.      index[i] = 0;
  249.  
  250.  
  251.  printf("\nWelcome to Speech Recognition Demo, Version 1.0\n");
  252.  
  253.  debug = 1;             /* display debugging information */
  254.  do
  255.   {
  256.      printf("\n\nTrain, Perform, Load A or B, Debug ");
  257.     if (debug) printf("Off"); else printf("On");
  258.     printf(", or Quit? (T/P/A/B/D/Q)");
  259.      gets(ans);
  260.      choice = toupper(ans[0]);
  261.      if (choice == 'A')
  262.     {
  263.       eztrain("a0",0); eztrain("a1",1); eztrain("a2",2);
  264.       eztrain("a3",3); eztrain("a4",4); eztrain("a5",5);
  265.       eztrain("a6",6); eztrain("a7",7); eztrain("a8",8);
  266.       eztrain("a9",9);
  267.     }
  268.      if (choice == 'B')
  269.     {
  270.       eztrain("b0",0); eztrain("b1",1); eztrain("b2",2);
  271.       eztrain("b3",3); eztrain("b4",4); eztrain("b5",5);
  272.       eztrain("b6",6); eztrain("b7",7); eztrain("b8",8);
  273.       eztrain("b9",9);
  274.     }
  275.      if (choice == 'D')
  276.     {
  277.       debug = !debug;
  278.       printf("\n    Debugging Trace ");
  279.       if (debug) printf("On"); else printf("Off");
  280.     }
  281.      if (choice == 'T') train();
  282.      if (choice == 'P') perform();
  283.   }
  284.   while(choice != 'Q');
  285.  printf("\n\nAll done.");
  286. }
  287.